home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
NOVA - For the NeXT Workstation
/
NOVA - For the NeXT Workstation.iso
/
SourceCode
/
AdobeExamples
/
NX_ImportAdv
/
rotateprocs.c
< prev
next >
Wrap
Text File
|
1992-12-19
|
6KB
|
219 lines
/*
* (a) (C) 1990 by Adobe Systems Incorporated. All rights reserved.
*
* (b) If this Sample Code is distributed as part of the Display PostScript
* System Software Development Kit from Adobe Systems Incorporated,
* then this copy is designated as Development Software and its use is
* subject to the terms of the License Agreement attached to such Kit.
*
* (c) If this Sample Code is distributed independently, then the following
* terms apply:
*
* (d) This file may be freely copied and redistributed as long as:
* 1) Parts (a), (d), (e) and (f) continue to be included in the file,
* 2) If the file has been modified in any way, a notice of such
* modification is conspicuously indicated.
*
* (e) PostScript, Display PostScript, and Adobe are registered trademarks of
* Adobe Systems Incorporated.
*
* (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
* CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
* AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
* ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
* OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
* WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
* WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
* DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
* OF THIRD PARTY RIGHTS.
*/
/*
* rotateprocs.c
*
* This file contains procedure that perform operations
* on rotated rectangles and points.
*
* Note: the angle in the procedures below should be expressed
* in radians and not degrees.
*/
#import <appkit/graphics.h>
#import <appkit/nextstd.h>
#import <math.h>
/*
* Takes the point passed in, rotates it around the point
* at the angle given and returns the new point.
* The new point replaces the old one and its address
* is returned as the return value.
*/
NXPoint *RotatePoint(NXPoint *aPoint, NXPoint *cPoint, float angle)
{
float d, dx, dy;
float ang;
if (aPoint && cPoint && angle != 0)
{
dx = aPoint->x - cPoint->x;
dy = aPoint->y - cPoint->y;
*aPoint = *cPoint;
d = sqrt(dx * dx + dy * dy);
if (d != 0.0)
{
ang = angle + (float) atan2(dy, dx);
aPoint->x += d * cos(ang);
aPoint->y += d * sin(ang);
}
}
return aPoint;
}
/*
* Checks whether the point passed in lies in the rectangle
* rotated about its lower left vertice at the angle provided.
* Returns either YES or NO. Assumes an unflipped
* coordinate system.
*/
BOOL MouseInRotatedRect(NXPoint *aPoint, NXRect *aRect, float angle)
{
NXPoint pt;
if (aRect && aPoint)
{
pt = *aPoint;
RotatePoint(&pt, &aRect->origin, -angle);
return NXMouseInRect(&pt, aRect, NO);
}
else
return NO;
}
/*
* This procedure takes the unrotated rectangle, bRect,
* rotates it around the point, cPoint, at the angle, angle,
* and places the new bounding box that encloses the
* rotated rectangle in the rectangle aRect. The address
* of the new rectangle is returned as the return value.
*
* Figuring the new width and height is relatively
* straight-forward. Just take the sin and cos of the
* old width and height.
*
* Figuring the new origin is a bit different. The vertices
* for the lower x and lower y coordinates are chosen
* based on the angle to rotate. Their positions in the rotated
* spaced are calculated and subtracted from the center point.
*/
NXRect *RotateRectBounds(NXRect *aRect, const NXRect *bRect, NXPoint *cPoint, float angle)
{
float dx, dy, dxx, dxy, dyx, dyy;
double cosa, sina;
if (aRect && bRect && cPoint)
{
if (angle != 0)
{
cosa = cos(angle);
sina = sin(angle);
dyx = dxx = bRect->origin.x - cPoint->x;
dyy = dxy = bRect->origin.y - cPoint->y;
if (cosa > 0)
{
if (sina > 0)
dxy += bRect->size.height;
else
dyx += bRect->size.width;
}
else
{
if (sina > 0)
{
dxx += bRect->size.width;
dyy = dxy = dxy + bRect->size.height;
}
else
{
dyx = dxx = dxx + bRect->size.width;
dyy += bRect->size.height;
}
}
aRect->origin = *cPoint;
dx = sqrt(dxx * dxx + dxy * dxy);
if (dx != 0.0)
aRect->origin.x += (float) dx * cos(angle + atan2(dxy, dxx));
dy = sqrt(dyx * dyx + dyy * dyy);
if (dy != 0.0)
aRect->origin.y += (float) dy * sin(angle + atan2(dyy, dyx));
aRect->size.width = (float) (ABS(bRect->size.width * cosa) +
ABS(bRect->size.height * sina));
aRect->size.height = (float) (ABS(bRect->size.width * cos(M_PI_2 - angle)) +
ABS(bRect->size.height * sin(M_PI_2 - angle)));
}
else
*aRect = *bRect;
}
return aRect;
}
/*
* This procedure takes two rectangles and an angle.
* It checks if the second rectangle rotated about its origin
* at the given angle intersects the first rectangle. The
* first rectangle is unrotated.
*
* It checks for intersection by getting the frame for the rotated
* rectangle and then checking the intersection.
*/
BOOL IntersectsRotatedRect(NXRect *aRect, NXRect *bRect, float angle)
{
NXRect rect;
if (aRect && bRect)
{
if (angle != 0.0)
{
RotateRectBounds(&rect, bRect, &bRect->origin, angle);
bRect = ▭
}
return NXIntersectsRect(aRect, bRect);
}
return NO;
}
/*
* This procedure takes two points and constrains the first
* point to the nearest 15% interval.
*/
void ConstrainPointToAngle(NXPoint *aPoint, NXPoint *cPoint, float angle)
{
float d, dx, dy, a;
dx = aPoint->x - cPoint->x;
dy = aPoint->y - cPoint->y;
d = sqrt(dx*dx + dy*dy);
if (d != 0.0)
{
a = rint(atan2(dy, dx) / angle) * angle;
aPoint->x = (float) cPoint->x + d * cos(a);
aPoint->y = (float) cPoint->y + d * sin(a);
}
}